home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-02-19 | 64.0 KB | 2,446 lines |
- Newsgroups: comp.sources.unix
- From: brnstnd@nyu.edu (Dan Bernstein)
- Subject: v25i129 REPOST: Generalized interface to pseudo-tty devices, Part03/09
- Sender: unix-sources-moderator@pa.dec.com
- Approved: vixie@pa.dec.com
-
- [ the first version of part03 had a raw \r floating around in one of
- the strings, and nntp doesn't do well with this. i changed the raw
- \r to a "\r" that the c compiler will convert back to a raw one. --vix ]
-
- Submitted-By: brnstnd@nyu.edu (Dan Bernstein)
- Posting-Number: Volume 25, Issue 129
- Archive-Name: pty4/part03
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 3 (of 9)."
- # Contents: CHANGES CHECKCONF.c IMPACT WTF getopt.c pty-basic.1
- # ptycomm.c ptyget.c ptyslave.c ptytexts.c radixsort.3 ralloc.c
- # sesslist.c sessmenu.c sessname.c sigdfl.c who.c write.c
- # Wrapped by vixie@cognition.pa.dec.com on Wed Feb 19 13:35:03 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'CHANGES' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'CHANGES'\"
- else
- echo shar: Extracting \"'CHANGES'\" \(3883 characters\)
- sed "s/^X//" >'CHANGES' <<'END_OF_FILE'
- X2/9/92: pty 4.0.
- X2/9/92: Fixed up documentation, hopefully for the last time.
- X1/29/92: Changed INSTALL.c to report chown root for INSTALL root. Tnx IS.
- X1/27/92: Added ABRT->IOT ifndef in sigdfl.c.
- X1/27/92: Changed sigdfl.c to zero the sigvecs rather than setting sv_flags.
- X1/16/92: pty 4.0, second gamma.
- X1/13/92: Does it work on an Iris? Nobody knows.
- X1/13/92: Added IRIS_UGH_PTYS to ptyget.c. Tnx IRIS, I think.
- X1/13/92: Changed fatal to warning for tctpgrp failure in ptyslave.c. Tnx IRIS.
- X1/13/92: ifndef'ed SYSV for ut_host in ptylogs.c. Tnx IRIS.
- X1/13/92: Added config/sysv.h to distribution. Tnx IRIS.
- X1/13/92: Added PTYLIBS, noted its use in README. Tnx IRIS.
- X1/13/92: Replaced CCOPTMZ with OPTMZ.
- X1/13/92: Noted in CALLS that TTY_TERMIO seems to work. Tnx IRIS.
- X1/13/92: Adapted tty_initmodes for TTY_TERMIO. Ugh, ugh. Tnx IRIS.
- X1/13/92: Adapted tty_mungemodes for TTY_TERMIO. Ugh. Tnx IRIS.
- X1/13/92: Adapted tty_modifymodes for TTY_TERMIO (poorly). Tnx IRIS.
- X1/13/92: Adapted tty_getmodes and tty_setmodes for TTY_TERMIO. Tnx IRIS.
- X1/13/92: In ptytty.c used ifdefs for FIONREAD and TIOCEXCL. Tnx IRIS.
- X1/13/92: Adapted ptytty.h for TTY_TERMIO. Tnx IRIS.
- X1/13/92: Added TTY_TERMIO option to config/ttyopts.h. Tnx IRIS.
- X1/13/92: Gave in and made tty_copymodes do a struct copy.
- X1/13/92: Fixed typo in SECURITY. Tnx KS.
- X1/13/92: Fixed typo in pty-basic.1. Tnx KS.
- X1/12/92: Replaced <sgtty.h> with <sys/ioctl.h> in ptytty.h. Tnx IRIS.
- X1/12/92: Added chmod 700 for all shell scripts in Makefile.
- X1/12/92: Removed <sys/timeb.h> from wall.c and write.c. Tnx IRIS.
- X1/12/92: In separate effort got it working on an IRIS. See above.
- X12/22/91: pty 4.0, first gamma! (Still have to integrate BSD 4.4 version.)
- X12/22/91: Changed various things in the documentation.
- X12/22/91: Fixed exit code reporting for, e.g., DIE_NOPTYS.
- X12/22/91: Changed POSIX to POSIX_SILLINESS. See config/posix.h.
- X12/20/91: Added CCOPTMZ in Makefile for radixsort.
- X12/19/91: Added BLURB.
- X12/19/91: Added TESTS.
- X12/19/91: Cleaned up README.
- X12/19/91: Added WTF, noted SunOS 4.0.3 forcefg bug in README.
- X12/18/91: Fixed bug in sessmenu's sesslist parsing.
- X12/17/91: Fixed up documentation a bit; referred to checkptys in README.
- X12/16/91: Added CPP define to Makefile.
- X12/15/91: Added -xi.
- X12/15/91: Started machine list in Makefile.
- X12/15/91: Added EWOULDBLOCK in ptysecure.c for Domain/OS.
- X12/14/91: Added target-list target.
- X12/14/91: Added lint target.
- X12/13/91: Changed master so that it continues child on any reconnect. Tnx SS.
- X11/24/91: Changed master to run only as effective uid.
- X11/18/91: Added TERM, USR1, USR2 ignoring to master. Tnx SS.
- X11/9/91: Added \fP in syntax sections in pty-opts.1, pty.1. Tnx SS.
- X11/9/91: Added <sys/types.h> before <utmp.h> in {users,who}.c. Domain/OS idiocy.
- X11/9/91: Fixed dependencies for CHECKCONF and INSTALL.
- X11/3/91: Added proper .h dependencies in Makefile (finally).
- X10/27/91: Added exit(0) at end of sesslist.c. Tnx SS.
- X10/27/91: Fixed ptysecure.c---it didn't undo chmod for some setups. Tnx SS.
- X10/27/91: Added make clean. Tnx SS.
- X10/27/91: Added checkptys.8.
- X10/27/91: Changed checkptys to be installed non-setuid.
- X10/26/91: Added pty.1, pty-basic.1, pty-opts.1, sess.1, condom.1.
- X10/26/91: Tossed old man pages.
- X10/26/91: Added DIE_EXIST for ptysigler.c.
- X10/26/91: Added DIE_ELSE for ptysigler.c.
- X10/26/91: Fixed ptymain to die(SETMODES) in an impossible situation.
- X10/26/91: Changed a few die() values in ptymain.c.
- X10/25/91: Need to add *.h to Makefile...
- X10/25/91: Removed last traces of old getopt schizophrenia.
- X10/25/91: Changed *rotate to preserve modes of log files.
- X10/25/91: Added sessnowinit, scnowinit.
- X10/25/91: Added sessrotate, sclogrotate.
- X10/25/91: Fixed off-by-one on remotelen.
- X10/25/91: Changed wtmprotate to depend on config/wtmpfile.h properly.
- X[log is not complete before this point]
- X10/6/91: Added -xsS.
- X9/30/91: pty 4.0, second beta.
- END_OF_FILE
- if test 3883 -ne `wc -c <'CHANGES'`; then
- echo shar: \"'CHANGES'\" unpacked with wrong size!
- fi
- # end of 'CHANGES'
- fi
- if test -f 'CHECKCONF.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'CHECKCONF.c'\"
- else
- echo shar: Extracting \"'CHECKCONF.c'\" \(2724 characters\)
- sed "s/^X//" >'CHECKCONF.c' <<'END_OF_FILE'
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/time.h>
- X#include <sys/stat.h>
- X#include <sys/file.h>
- X#include "config/fdsettrouble.h"
- X#include "config/genericptr.h"
- X#include "config/devmty.h"
- X#include "config/devsty.h"
- X#include "config/posix.h"
- X#include "config/ptybin.h"
- X#include "config/ptydir.h"
- X#include "config/ptyext.h"
- X#include "config/ptygroup.h"
- X#include "config/ptylongname.h"
- X#include "config/ptymodes.h"
- X#include "config/ptyopts.h"
- X#include "config/ttyopts.h"
- X#include "config/sessconnfile.h"
- X#include "config/sessfile.h"
- X#include <utmp.h>
- X#include "config/utmpfile.h"
- X#include "config/wtmpfile.h"
- X#include <grp.h>
- X
- main()
- X{
- X int nothing;
- X struct group *grp;
- X printf("Check through this list carefully.\n");
- X printf("master tty extension: %s\n",DEVMTY);
- X printf("slave tty extension: %s\n",DEVSTY);
- X printf("pty names: %s[%s][%s]\n",DEVMTY,PTYEXT1,PTYEXT2);
- X printf("pty binary directory: %s\n",PTYBIN);
- X printf("pty session directory: %s\n",PTYDIR);
- X printf("utmp file: %s wtmp file: %s\n",UTMP_FILE,WTMP_FILE);
- X printf("session-connection now: %s log: %s\n",SESSCONNNOW_FILE,SESSCONNLOG_FILE);
- X printf("session now: %s log: %s\n",SESSNOW_FILE,SESSLOG_FILE);
- X#ifdef DESPERATE_FD_SET
- X printf("DESPERATE_FD_SET turned on.\n");
- X#else
- X#ifdef LACKING_FD_ZERO
- X printf("LACKING_FD_ZERO turned on.\n");
- X#else
- X printf("System must have normal fd_set and FD_ZERO support.\n");
- X#endif
- X#endif
- X /* XXX: GENERICPTR? */
- X#ifdef POSIX_SILLINESS
- X printf("POSIX turned on. System must have setsid().\n");
- X#else
- X printf("POSIX turned off. System should not have setsid().\n");
- X#endif
- X printf("pty group: %d. ",PTYGROUP);
- X grp = getgrnam("tty");
- X if (!grp)
- X printf("\nAack! You should add a tty group, group %d, to /etc/group.\n",PTYGROUP);
- X else
- X if (grp->gr_gid == PTYGROUP)
- X printf("Okay, this matches the tty entry in /etc/group.\n");
- X else
- X printf("\nAack! This doesn't match the tty group entry (%d) in /etc/group.\nYou should probably edit config/ptygroup.h.\n",grp->gr_gid);
- X printf("session long name length: %d\n",PTYLONGNAMELEN);
- X printf("pty modes: %o used %o unused\n",PTYMODE_USED,PTYMODE_UNUSED);
- X printf("MUSTNOT: "); nothing = 1;
- X#ifdef PTY_MUSTNOT_SESSION
- X printf("session "); nothing = 0;
- X#endif
- X#ifdef PTY_MUSTNOT_UTMPHOST
- X printf("utmphost "); nothing = 0;
- X#endif
- X#ifdef PTY_MUSTNOT_UTMP
- X printf("utmp "); nothing = 0;
- X#endif
- X#ifdef PTY_MUSTNOT_WTMP
- X printf("wtmp "); nothing = 0;
- X#endif
- X#ifdef PTY_MUSTNOT_CHOWN
- X printf("chown "); nothing = 0;
- X#endif
- X if (nothing) printf("(nothing)");
- X printf("\n");
- X#ifdef TTY_AUXCHARS
- X printf("System must support tty auxiliary characters.\n");
- X#endif
- X#ifdef TTY_WINDOWS
- X printf("System must support tty windows and SIGWINCH.\n");
- X#endif
- X exit(0);
- X}
- END_OF_FILE
- if test 2724 -ne `wc -c <'CHECKCONF.c'`; then
- echo shar: \"'CHECKCONF.c'\" unpacked with wrong size!
- fi
- # end of 'CHECKCONF.c'
- fi
- if test -f 'IMPACT' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'IMPACT'\"
- else
- echo shar: Extracting \"'IMPACT'\" \(2458 characters\)
- sed "s/^X//" >'IMPACT' <<'END_OF_FILE'
- X [ pty ]
- X> Is it self-contained, or does it
- X> require other mods?
- X
- There are certain decisions which anyone installing pty has to make:
- X
- X1. Should pty run setuid root, or setuid some other user, say ``pty''?
- If the latter, then the new user should be added to /etc/passwd, and it
- would help to have utmp and wtmp owned by that user. It's generally
- simpler to have pty running setuid root. This also lets it chown and
- chmod tty device files.
- X
- X2. pty's INSTALL program copies the binaries to some directory, and sets
- up a directory where pty can store session information. Where do those two
- directories go? The defaults are /usr/local/ptybin and /usr/local/etc/pty.
- pty also maintains four session log files analogous to utmp/wtmp, all in
- X/usr/local/etc by default.
- X
- X3. pty comes with some clones of existing programs: biff, lock, mesg,
- script, tty, users, wall, who, whoami, write. In many cases these offer
- features beyond the standard versions: for instance, if pty has write
- permission to utmp, then script (which is just a tiny shell script) will
- have a utmp entry, so talk/mail/write/etc. will work. Should they
- replace the system versions?
- X
- X4. pty comes with some programs which belong in rc.local: utmpinit does a
- more professional job of utmp initialization than init does; sessnowinit
- and scnowinit initialize pty's session log files. Should these be added to
- rc.local?
- X
- X5. pty comes with some programs which belong in daily, weekly, or monthly
- cron scripts: wtmprotate, sessrotate, and sclogrotate. On any modern
- system, of course, wtmp is rotated anyway, but should sessrotate and
- sclogrotate be added to cron scripts? One other program, checkptys,
- produces a report on the entire pty subsystem, and can also be run from
- cron.
- X
- X6. pty comes with some other utilities not directly related to session
- management. For instance, trecord and tplay make typescripts in a
- special format which includes the timing between characters. My tscript
- utility works just like script but makes a tapescript which you can play
- back later. (This is great for talk conversations and other interactive
- sessions.) Should these utilities be part of a user's standard path?
- Should pty itself be part of a user's standard path?
- X
- X7. Should some secure ttys be set aside for pty's use? It's easy to
- configure pty so that it only uses (e.g.) tty[u-z]*, which are always
- mode 600 root rather than mode 666 root. Or pty can just compete for
- insecure ttys like everyone else.
- END_OF_FILE
- if test 2458 -ne `wc -c <'IMPACT'`; then
- echo shar: \"'IMPACT'\" unpacked with wrong size!
- fi
- # end of 'IMPACT'
- fi
- if test -f 'WTF' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'WTF'\"
- else
- echo shar: Extracting \"'WTF'\" \(2353 characters\)
- sed "s/^X//" >'WTF' <<'END_OF_FILE'
- BLURB: general blurb on what pty does for you.
- X
- README: the first thing you should read; gives basic information and
- credits, and tells you how to get pty running.
- X
- XFORMLETTER: the form letter you should send back to me when you get to
- step #12 in README.
- X
- SYSCONF: a shell script which looks for various features of your system
- and changes config/* accordingly.
- X
- WTF: this file, detailing what the, uh, files in this distribution are
- for.
- X
- CALLS: a detailed list of all the syscalls and library calls used by
- pty, followed by a breakdown of the calls into groups and a description
- of what you have to do to port each group. This is the most important
- file to read if you're going to port pty to a non-BSD system.
- X
- CHANGES: reverse chronological list of most of the changes to pty 4.0.
- X
- COPYRIGHT: short explanation of the copying rights I'm giving you.
- X
- XFILES: list of all the files in the pty 4.0 distribution, in some order;
- used by ``make shar'', for example.
- X
- OBJECTS: list of all the .o files created while compiling pty.
- X
- BINARIES: list of all the executables created by ``make''.
- X
- Makefile: instructions for make, in a reasonably portable format.
- X
- TESTS: typescript of a typical pty test run.
- X
- NEW: explanation of the important differences between pty 3.0 and pty 4.0.
- X
- NOTES: random implementation notes. This is the first place to turn to
- if you're not sure about something in the code.
- X
- IMPACT: rough outline of how pty affects the rest of the system.
- X
- SECURITY: dull explanation of the incredible torture pty 4.0 has to go
- through to ensure that a tty is ``clean''.
- X
- QUESTIONS: questions and pty-based answers, mostly stolen from the
- USENET newsgroup comp.unix.questions.
- X
- X*.draft*: draft papers dealing with random topics of possible interest.
- SESS.draft2 leads the reader through a session management tutorial.
- X
- X*.1: man pages for user programs.
- X
- X*.3: man pages for libraries.
- X
- X*.7: man pages giving general information.
- X
- X*.8: man pages for sysadmin programs.
- X
- X*.c: C source files.
- X
- X*.h: C header files.
- X
- X*.sh: sh source files. Makefile does the work of ``compiling'' these.
- X
- config/*.h: configuration files. Instead of a big config.h, or lots of
- options spread through Makefile or through individual files, all
- compile-time options are collected here. SYSCONF edits some of these.
- You can edit them too. Or steal them for other programs.
- END_OF_FILE
- if test 2353 -ne `wc -c <'WTF'`; then
- echo shar: \"'WTF'\" unpacked with wrong size!
- fi
- # end of 'WTF'
- fi
- if test -f 'getopt.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'getopt.c'\"
- else
- echo shar: Extracting \"'getopt.c'\" \(3276 characters\)
- sed "s/^X//" >'getopt.c' <<'END_OF_FILE'
- X/* getopt.c, getopt.h: (yet another) improved getopt clone
- Daniel J. Bernstein, brnstnd@nyu.edu.
- No dependencies.
- Requires stdio.
- X10/20/91: Removed -DGETOPT_SHUT_UP. [sigh]
- X8/26/91: Added -DGETOPT_SHUT_UP.
- X8/25/91: Changed getopt to not skip blank arguments.
- X7/6/91: Baseline. getopt 1.0, public domain.
- No known patent problems.
- X
- This is a clone of the usual getopt() functions. It includes opterr so
- that you can turn off error handling, optpos so that you can find out
- exactly where the processing is up to (instead of just which argument),
- optproblem so that you can accurately diagnose errors yourself, and
- optprogname so that you can set the program name for getopt-generated
- errors. getopt() takes much more care to ensure that all the variables
- still make sense upon errors and EOF. (optproblem is a character. If
- argv[optind] is 0, the problem is a missing argument; otherwise it's an
- illegal option character.) Unless you define GETOPTORIGDEF, the header
- file redefines all names so that you don't have to worry about conflicts
- with libc. Finally, the code is public-domain, so you should feel free
- to use these extra features in your own programs and just attach a copy
- of this.
- X
- Note that optind and optpos can be read (or set) any time, but the
- official getopt interface only defines optind when getopt() returns EOF.
- We define optproblem only when getopt() returns '?', optarg all the
- time, and optprogram only after getopt() has been called at least once.
- X
- X*/
- X
- X#include <stdio.h> /* for EOF and stderr---talk about immodularity! */
- X#include "getopt.h"
- X
- int optind = 1;
- int optpos = 0;
- int opterr = 1;
- char *optarg = 0;
- int optproblem = 0;
- char *optprogname = 0;
- int opteof = EOF;
- X
- int getopt(argc,argv,opts)
- int argc;
- char **argv;
- char *opts;
- X{
- X int c;
- X char *s;
- X
- X optarg = 0;
- X if (!optprogname)
- X {
- X optprogname = *argv;
- X if (!optprogname) /* oh boy */
- X optprogname = ""; /*XXX*/
- X for (s = optprogname;*s;++s)
- X if (*s == '/')
- X optprogname = s + 1;
- X }
- X if (!argv || (optind >= argc) || !argv[optind])
- X return opteof;
- X while (optpos && !argv[optind][optpos])
- X {
- X /* we simply skip blank arguments... not any more */
- X ++optind;
- X optpos = 0;
- X if ((optind >= argc) || !argv[optind])
- X return opteof;
- X }
- X if (!optpos)
- X {
- X if (argv[optind][0] != '-')
- X return opteof;
- X ++optpos;
- X c = argv[optind][1];
- X if ((c == '-') || (c == 0))
- X {
- X /* XXX: this behavior of "-" is stupid */
- X if (c)
- X ++optind;
- X optpos = 0;
- X return opteof;
- X }
- X /* otherwise c is reassigned below */
- X }
- X c = argv[optind][optpos];
- X ++optpos;
- X s = opts;
- X while (*s)
- X {
- X if (c == *s)
- X {
- X if (s[1] == ':')
- X {
- X optarg = argv[optind] + optpos;
- X ++optind;
- X optpos = 0;
- X if (!*optarg)
- X {
- X optarg = argv[optind];
- X if ((optind >= argc) || !optarg) /* argument past end */
- X {
- X optproblem = c;
- X if (opterr)
- X fprintf(stderr,"%s: option requires an argument -- %c\n"
- X ,optprogname,c);
- X return '?';
- X }
- X ++optind;
- X }
- X }
- X return c;
- X }
- X ++s;
- X if (*s == ':')
- X ++s;
- X }
- X optproblem = c;
- X if (opterr)
- X fprintf(stderr,"%s: illegal option -- %c\n",optprogname,c);
- X return '?';
- X}
- END_OF_FILE
- if test 3276 -ne `wc -c <'getopt.c'`; then
- echo shar: \"'getopt.c'\" unpacked with wrong size!
- fi
- # end of 'getopt.c'
- fi
- if test -f 'pty-basic.1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'pty-basic.1'\"
- else
- echo shar: Extracting \"'pty-basic.1'\" \(3127 characters\)
- sed "s/^X//" >'pty-basic.1' <<'END_OF_FILE'
- X.TH pty-basic 1
- X.SH NAME
- pty-basic \- run a program under a pseudo-terminal session
- X.SH SYNTAX
- pty
- X.I program
- X[
- X.I arg ...
- X]
- X.SH DESCRIPTION
- This man page describes the effects of
- X.B pty
- without any options.
- XFor a general overview of
- X.B pty,
- see the
- X.B pty(1)
- man page.
- XFor a description of
- the options,
- see the
- X.B pty-opts(1)
- man page.
- X
- XExecuting
- X.B pty \fIprogram
- has approximately the same effect as executing
- X.I program
- X(with zero or more arguments).
- X.I program
- is run under a pseudo-terminal. This means several things:
- X
- X1. Its standard input, output, and error descriptors are redirected to a
- pseudo-terminal device driver, with effects documented in
- X.B pty(4)
- and
- X.B tty(4).
- This means that
- X.I program
- may use
- X.B ioctl(),
- for example, to affect the
- pseudo-terminal.
- So programs such as
- X.B vi,
- which normally cannot be run
- inside a pipe, will see a terminal instead.
- X(Of course,
- X.B pty
- may be put
- into a pipe.)
- X
- X2.
- X.B isatty()
- and stdio's buffering will consider those descriptors to be
- pointing to a terminal, with effects documented in
- X.B isatty(3)
- and
- X.B setbuf(3).
- This means that if
- X.I program
- uses stdio, its output will be
- line-buffered.
- X
- X3. Input to
- X.B pty \fIprogram
- is passed through to the pseudo-terminal
- input. Output and error to the pseudo-terminal are passed through to the
- output of
- X.B pty \fIprogram.
- X
- X4.
- X.I program
- has controlling terminal set to the pseudo-terminal, with
- effects documented in
- X.B tty(4).
- X
- X5.
- X.B pty \fIprogram
- must have an original controlling tty.
- X.B pty
- considers the controlling tty to be the first of
- the following which responds to a TIOCGPGRP ioctl:
- descriptor 3, /dev/tty, descriptor 0, descriptor 1,
- descriptor 2.
- X.B pty
- sets that terminal to character-at-a-time, no-echo mode,
- to do as little processing as possible.
- It sets the pseudo-terminal to the original mode.
- When
- X.I program
- finishes,
- X.B pty
- sets the original terminal back to its original mode.
- Any mode changes on the pseudo-terminal will be lost.
- The original terminal is also reset whenever
- X.I program
- is stopped
- X(and then set back to character-at-a-time mode when
- X.I program
- is restarted).
- X
- X6.
- Various signals to
- X.B pty \fIprogram
- are converted into HUPs for
- X.I program.
- Single-process signals may fail upon
- X.B pty \fIprogram.
- Process group signals as described in
- X.B tty(4)
- will affect it normally.
- X
- X7.
- All normal exits (including signal exits) for
- X.I program
- are converted
- into exit code 0.
- Other exit codes indicate various new,
- pty-related problems, which are also announced on the standard error of
- X.B pty \fIprogram.
- X
- X8.
- All file descriptors except 0, 1, and 2 are closed.
- X3 is reopened as the new /dev/tty,
- i.e.,
- the pseudo-terminal.
- All controlling terminal ioctls
- mentioned in
- X.B tty(4)
- may be applied to file descriptor 3 instead.
- X
- Note that
- X.B pty
- transmits job control transparently:
- if
- X.I program
- stops with (say)
- a TTIN, then
- X.B pty \fIprogram
- will also stop with a TTIN.
- When
- X.B pty \fIprogram
- is continued,
- X.I program
- will receive a CONT.
- X.SH VERSION
- pty version 4.0, 2/9/92.
- X.SH AUTHOR
- Copyright 1992, Daniel J. Bernstein.
- X.SH "SEE ALSO"
- pty(1),
- pty-opts(1),
- sess(1),
- condom(1),
- pty(4),
- tty(4)
- END_OF_FILE
- if test 3127 -ne `wc -c <'pty-basic.1'`; then
- echo shar: \"'pty-basic.1'\" unpacked with wrong size!
- fi
- # end of 'pty-basic.1'
- fi
- if test -f 'ptycomm.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'ptycomm.c'\"
- else
- echo shar: Extracting \"'ptycomm.c'\" \(3465 characters\)
- sed "s/^X//" >'ptycomm.c' <<'END_OF_FILE'
- X#include <sys/types.h>
- X#include <sys/time.h>
- X#include <sys/socket.h>
- X#include <sys/un.h>
- X#include <sys/uio.h>
- X#include <errno.h>
- extern int errno;
- X#include "fmt.h"
- X#include "config/ptyext.h"
- X#include "ptycomm.h"
- X#include "ptymisc.h"
- X
- X/*
- Under most versions of SunOS and Ultrix, as well as lots of other systems,
- file descriptor passing doesn't work. The most important problem is that
- in some situations recvmsg() may return 0 without actually waiting to
- receive the file descriptors; in other words, msg_accrightslen may be
- sporadically 0. The workaround here is to pause very briefly (1/100 of a
- second) and try the recvmsg() again, up to 100 times. I'd prefer seeing
- the bug fixed.
- X*/
- X
- X#define ESTUPID EINPROGRESS /* [sigh] */
- X
- static int comm_path(s,ext,uid)
- char *s;
- char *ext;
- int uid;
- X{
- X int i;
- X char *t;
- X
- X/* as a last layer of protection we make sure that we only create */
- X/* valid filenames... */
- X for (i = 0;PTYEXT1[i];++i)
- X if (ext[0] == PTYEXT1[i])
- X break;
- X if (!PTYEXT1[i])
- X return -1;
- X for (i = 0;PTYEXT2[i];++i)
- X if (ext[1] == PTYEXT2[i])
- X break;
- X if (!PTYEXT2[i])
- X return -1;
- X t = s;
- X t += fmt_strncpy(t,"comm.",0);
- X t += fmt_uint(t,uid);
- X *t++ = '.';
- X *t++ = ext[0];
- X *t++ = ext[1];
- X *t = 0;
- X return 0;
- X}
- X
- int comm_read(ext,uid)
- char *ext;
- int uid;
- X{
- X int s;
- X struct sockaddr_un sa;
- X
- X if ((s = socket(AF_UNIX,SOCK_STREAM,0)) == -1)
- X return -1;
- X sa.sun_family = AF_UNIX;
- X if (comm_path(sa.sun_path,ext,uid) == -1)
- X return -1;
- X unlink(sa.sun_path);
- X if (bind(s,(struct sockaddr *) &sa,strlen(sa.sun_path) + 2) == -1)
- X return -1;
- X if (listen(s,5) == -1)
- X return -1;
- X return s;
- X}
- X
- int comm_accept(fd)
- int fd;
- X{
- X struct sockaddr_un sa;
- X int salen;
- X salen = sizeof(sa);
- X return accept(fd,(struct sockaddr *) &sa,&salen);
- X}
- X
- int comm_unlink(ext,uid)
- char *ext;
- int uid;
- X{
- X struct sockaddr_un sa;
- X if (comm_path(sa.sun_path,ext,uid) == -1)
- X return -1;
- X return unlink(sa.sun_path);
- X}
- X
- int comm_write(ext,uid)
- char *ext;
- int uid;
- X{
- X int s;
- X struct sockaddr_un sa;
- X
- X if ((s = socket(AF_UNIX,SOCK_STREAM,0)) == -1)
- X return -1;
- X sa.sun_family = AF_UNIX;
- X if (comm_path(sa.sun_path,ext,uid) == -1)
- X return -1;
- X if (connect(s,(struct sockaddr *) &sa,strlen(sa.sun_path) + 2) == -1)
- X return -1;
- X return s;
- X}
- X
- int csp(fdcomm,fd)
- int fdcomm;
- int fd;
- X{
- X struct msghdr msg[2];
- X int acc[5];
- X struct iovec i[2];
- X
- X msg[0].msg_name = 0;
- X msg[0].msg_namelen = 0;
- X msg[0].msg_iov = i; /* grrrr */
- X msg[0].msg_iovlen = 0;
- X msg[0].msg_accrights = (caddr_t) acc;
- X msg[0].msg_accrightslen = sizeof(int);
- X
- X acc[0] = fd;
- X
- X return sendmsg(fdcomm,msg,0);
- X}
- X
- int comm_putfd(fdcomm,fd)
- int fdcomm;
- int fd;
- X{
- X int tries;
- X for (tries = 0;tries < 100;++tries)
- X if (csp(fdcomm,fd) == 0)
- X return 0;
- X return -1;
- X}
- X
- static int cgf(fdcomm)
- int fdcomm;
- X{
- X struct msghdr msg[2];
- X int acc[5];
- X struct iovec i[2];
- X int r;
- X
- X msg[0].msg_name = 0;
- X msg[0].msg_namelen = 0;
- X msg[0].msg_iov = i; /* grrrr */
- X msg[0].msg_iovlen = 0;
- X msg[0].msg_accrights = (caddr_t) acc;
- X msg[0].msg_accrightslen = sizeof(int);
- X
- X do
- X r = recvmsg(fdcomm,msg,0);
- X while ((r == -1) && ((errno == EINTR) || (errno == EWOULDBLOCK)));
- X if (r == -1)
- X return -1;
- X if (msg[0].msg_accrightslen != sizeof(int))
- X {
- X errno = ESTUPID; /* it didn't arrive. */
- X return -1;
- X }
- X return acc[0];
- X}
- X
- int comm_getfd(fdcomm)
- int fdcomm;
- X{
- X int fd;
- X int tries;
- X
- X for (tries = 0;tries < 100;++tries)
- X {
- X fd = cgf(fdcomm);
- X if (fd != -1)
- X return fd;
- X gaargh(10000);
- X }
- X return -1;
- X}
- END_OF_FILE
- if test 3465 -ne `wc -c <'ptycomm.c'`; then
- echo shar: \"'ptycomm.c'\" unpacked with wrong size!
- fi
- # end of 'ptycomm.c'
- fi
- if test -f 'ptyget.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'ptyget.c'\"
- else
- echo shar: Extracting \"'ptyget.c'\" \(3826 characters\)
- sed "s/^X//" >'ptyget.c' <<'END_OF_FILE'
- X#ifdef IRIS_UGH_PTYS
- X#include <fcntl.h>
- X#include <sys/types.h>
- X#include <sys/sysmacros.h>
- X#include <sys/stat.h>
- X#include <stdio.h>
- X#endif
- X#include <sys/file.h>
- X#include <errno.h>
- extern int errno;
- X#include "ptyget.h"
- X#include "config/ptyext.h"
- X#include "config/devmty.h"
- X#include "config/devsty.h"
- X#include "ptysecure.h"
- X
- static int gcd(x,y) /* assumes both nonnegative */
- int x; int y;
- X{
- X int t;
- X while (x && y) { t = x % y; x = y; y = t; }
- X return x ? x : y;
- X}
- X
- int ungetpty(fdmaster,fdslave,ext)
- int fdmaster;
- int fdslave;
- char *ext;
- X{
- X#ifdef IRIS_UGH_PTYS
- X return 0; /*XXX*/
- X#endif
- X /*XXXX*/
- X ptyunsecure(fdmaster,fdslave,ext);
- X /* XXX: close fdmaster and fdslave? nah */
- X}
- X
- static char fnmty[sizeof(DEVMTY) + 2] = DEVMTY;
- static char fnsty[sizeof(DEVSTY) + 2] = DEVSTY;
- X
- static char pty1[] = PTYEXT1;
- static char pty2[] = PTYEXT2;
- X#define pty1len (sizeof(pty1) - 1)
- X#define pty2len (sizeof(pty2) - 1)
- X
- static int bankok[pty1len]; /* must be initialized to 0! */
- X
- X/* not reentrant */
- int getfreepty(fdmaster,fdslave,ext,r1,r2,eachpty,flagxchown,allowinsecure)
- int *fdmaster;
- int *fdslave;
- char *ext;
- int r1;
- int r2; /* set both r1 and r2 to 0 for the standard searching order */
- int (*eachpty)();
- int flagxchown;
- int allowinsecure;
- X{
- X int start;
- X int increment;
- X int pos;
- X int p1;
- X int fdmty;
- X int fdsty;
- X
- X#ifdef IRIS_UGH_PTYS /* XXX: needless to say, deprecated */
- X
- char foo[200]; int ptynum; struct stat statmty;
- if (eachpty("xx") == -1) return -1;
- fdmty = open("/dev/ptc",O_RDWR | O_NDELAY);
- if (fdmty == -1) return -1;
- if (fstat(fdmty,&statmty) == -1) { close(fdmty); return -1; }
- ptynum = minor(statmty.st_rdev);
- sprintf(foo,"/dev/ttyq%d",ptynum);
- fdsty = open(foo,O_RDWR);
- X*fdmaster = fdmty; *fdslave = fdsty;
- ext[0] = 'a' + ptynum / 26;
- ext[1] = 'a' + ptynum % 26;
- return 0;
- X
- X#endif
- X
- X /* XXX: Here would be a good spot to include pty limits, say through */
- X /* the file PTYDIR/LIMITS. Lines of the form user group num, saying */
- X /* that user in that group is limited to num ptys, with * for all. */
- X /* All pty use would have to be logged somewhere. Anyway, with a */
- X /* streams-based pty, there wouldn't be much point to limits. */
- X
- X pos = pty1len * pty2len;
- X start = r1 % pos; if (start < 0) start += pos;
- X increment = r2 % pos; if (increment < 0) increment += pos;
- X
- X while (gcd(increment,pos) != 1)
- X ++increment; /* note that this weights some increments more heavily */
- X
- X fnmty[sizeof(DEVMTY) + 1] = 0;
- X fnsty[sizeof(DEVSTY) + 1] = 0;
- X
- X pos = start;
- X do
- X {
- X p1 = pos / pty2len;
- X fnmty[sizeof(DEVMTY) - 1] = pty1[p1];
- X if (!bankok[p1])
- X {
- X fnmty[sizeof(DEVMTY)] = pty2[0];
- X if (access(fnmty,F_OK) == -1)
- X bankok[p1] = -1;
- X else
- X bankok[p1] = 1;
- X }
- X if (bankok[p1] == 1) /* okay, we know bank exists. */
- X {
- X fnsty[sizeof(DEVMTY)] = fnmty[sizeof(DEVMTY)] = pty2[pos % pty2len];
- X fnsty[sizeof(DEVSTY) - 1] = pty1[p1];
- X if (eachpty(fnmty + sizeof(DEVMTY) - 1) == -1)
- X return -1;
- X do
- X fdmty = open(fnmty,O_RDWR);
- X while ((fdmty == -1) && (errno == EINTR));
- X if (fdmty != -1)
- X {
- X do
- X fdsty = open(fnsty,O_RDWR);
- X while ((fdsty == -1) && (errno == EINTR));
- X if (fdsty == -1)
- X close(fdmty); /* XXX: warning that slave isn't openable? */
- X else
- X {
- X setnonblock(fdmty); /*XXX*/
- X ext[0] = pty1[p1];
- X ext[1] = pty2[pos % pty2len];
- X /* Got both sides of the tty open! Now comes the tricky part. */
- X if (ptysecure(&fdmty,&fdsty,ext,fnmty,fnsty,flagxchown,allowinsecure) == -1)
- X {
- X /* XXX: warning of security violation? */
- X }
- X else
- X {
- X unsetnonblock(fdmty); /*XXX*/
- X /* It's ours. */
- X *fdmaster = fdmty;
- X *fdslave = fdsty;
- X return 0;
- X }
- X }
- X }
- X }
- X pos = (pos + increment) % (pty1len * pty2len);
- X }
- X while (pos != start);
- X
- X return -1; /* all unopenable? yikes */
- X}
- END_OF_FILE
- if test 3826 -ne `wc -c <'ptyget.c'`; then
- echo shar: \"'ptyget.c'\" unpacked with wrong size!
- fi
- # end of 'ptyget.c'
- fi
- if test -f 'ptyslave.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'ptyslave.c'\"
- else
- echo shar: Extracting \"'ptyslave.c'\" \(2764 characters\)
- sed "s/^X//" >'ptyslave.c' <<'END_OF_FILE'
- X#include <signal.h>
- X#include <sys/types.h>
- X#include <sys/file.h>
- X#include "fmt.h"
- X#include "ptyerr.h"
- X#include "ptyslave.h"
- X#include "ralloc.h"
- X
- void slave(fdsty,ext,program,flagxerrwo,flagsameerr,uid,flagverbose,flagxexcl)
- int fdsty;
- char *ext;
- char **program;
- int flagxerrwo;
- int flagsameerr;
- int uid;
- int flagverbose;
- int flagxexcl;
- X{
- X char ptyext[10];
- X int fdout;
- X int fdtty;
- X char *t;
- X
- X /* we're already dissociated and reassociated */
- X close(0);
- X close(1);
- X if (flagsameerr < 2)
- X close(2);
- X if (flagsameerr < 1)
- X {
- X close(3);
- X for (fdout = getdtablesize();fdout > 3;--fdout)
- X if (fdout != fdsty)
- X close(fdout);
- X }
- X if (dup(fdsty) != 0)
- X {
- X warn("fatal","cannot dup slave tty descriptor");
- X die(1);
- X }
- X if (dup(fdsty) != 1)
- X {
- X warn("fatal","cannot dup slave tty descriptor");
- X die(1);
- X }
- X if (flagsameerr < 2)
- X if (dup(fdsty) != 2) /* XXX: what about flagxerrwo? */
- X {
- X warn("fatal","cannot dup slave tty descriptor");
- X die(1);
- X }
- X if (flagsameerr < 1)
- X if (open("/dev/tty",O_RDWR) != 3)
- X {
- X warn("fatal","cannot open /dev/tty under pseudo-tty");
- X die(1);
- X }
- X close(fdsty);
- X
- X if ((fdtty = open("/dev/tty",O_RDWR)) == -1)
- X {
- X warn("fatal","cannot open /dev/tty second time under pseudo-tty");
- X die(1);
- X }
- X if (flagxexcl)
- X if (tty_setexcl(0) == -1)
- X warn("warning","cannot set exclusive use on pseudo-tty");
- X if (setpgrp(0,getpid()) == -1)
- X {
- X warn("fatal","cannot setpgrp");
- X die(1);
- X }
- X signal(SIGTTOU,SIG_IGN);
- X if (tctpgrp(fdtty,getpid()) == -1)
- X {
- X warn("warning","cannot set pseudo-tty pgrp");
- X /* XXX: this always seems to happen on an IRIS. why? */
- X }
- X signal(SIGTTOU,SIG_DFL);
- X /* pty modes are already set */
- X /* pty inode protection, including chmod and chown, is done */
- X close(fdtty);
- X
- X /* logs, including utmp and wtmp, are already set up */
- X
- X /* master's comm file is already set up. end of that race! */
- X
- X if (setreuid(uid,uid) == -1)
- X /* This syscall shouldn't ever fail, so most programs don't check it. */
- X /* But we absolutely refuse to exec while setuid. */
- X {
- X warn("fatal","cannot setreuid");
- X die(1);
- X }
- X
- X t = ptyext;
- X t += fmt_strncpy(ptyext,"PTY=",0);
- X *t++ = ext[0];
- X *t++ = ext[1];
- X *t = 0;
- X if (env_put(ptyext) == -1)
- X {
- X warn("fatal","cannot set up PTY in environment");
- X die(1);
- X }
- X
- X sigsetmask(0); /*XXX: restore exactly? */
- X
- X if (flagverbose > 1)
- X warn("executing program",program[0]);
- X execvp(program[0],program);
- X
- X {
- X char *buf;
- X buf = ralloc(strlen(program) + 30);
- X if (!buf)
- X warn("fatal","cannot exec");
- X else
- X {
- X t = buf;
- X t += fmt_strncpy(t,"cannot exec ",0);
- X t += fmt_strncpy(t,program[0],0);
- X *t = 0;
- X warn("fatal",buf);
- X rfree(buf);
- X }
- X }
- X die(1);
- X /*NOTREACHED*/
- X}
- END_OF_FILE
- if test 2764 -ne `wc -c <'ptyslave.c'`; then
- echo shar: \"'ptyslave.c'\" unpacked with wrong size!
- fi
- # end of 'ptyslave.c'
- fi
- if test -f 'ptytexts.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'ptytexts.c'\"
- else
- echo shar: Extracting \"'ptytexts.c'\" \(3662 characters\)
- sed "s/^X//" >'ptytexts.c' <<'END_OF_FILE'
- X#include "ptytexts.h"
- X
- char *ptyauthor = "\
- pty was written by Daniel J. Bernstein.\n\
- Internet address: brnstnd@nyu.edu.\n\
- X" ;
- X
- char *ptyversion = "\
- pty version 4.0, February 9, 1992.\n\
- Copyright (c) 1992, Daniel J. Bernstein.\n\
- All rights reserved.\n\
- X" ;
- X
- char *ptycopyright = "\
- pty version 4.0, February 9, 1992.\n\
- Copyright (c) 1992, Daniel J. Bernstein.\n\
- All rights reserved.\n\
- X\n\
- I want this program to be distributed freely in original form.\n\
- X\n\
- Once you've received a legal copy of this program, you can use it.\n\
- XForever. Nobody can take that right away from you. You can make changes\n\
- and backup copies for your use (or, if you're an organization, for the\n\
- use of everyone in the organization). You can distribute patches (though\n\
- not patched versions). You'd have all these rights even if I didn't tell\n\
- you about them.\n\
- X\n\
- I do grant you further rights, as detailed in the source package. Don't\n\
- worry about them unless you're planning to distribute further copies.\n\
- X\n\
- If you have questions about this program or about this notice, or if you\n\
- would like additional rights beyond those granted above, or if you have\n\
- a patch that you don't mind sharing, please contact me on the Internet\n\
- at brnstnd@nyu.edu.\n\
- X" ;
- X
- char *ptywarranty = "\
- Daniel J. Bernstein disclaims all warranties to the extent permitted\n\
- by applicable law. He is not and shall not be liable for any damages\n\
- arising from the use of this program. This disclaimer shall be governed\n\
- by the laws of the state of New York.\n\
- X\n\
- In other words, use this program at your own risk.\n\
- X\n\
- If you have questions about this program or about this disclaimer of\n\
- warranty, please contact me on the Internet at brnstnd@nyu.edu.\n\
- X" ;
- X
- char *ptyusage = "\
- Usage: pty [ -qQve3EdDjJsStTrR0ACHUVW ] [ -h host ] [ -O remote ]\n\
- X [ -p[cCdDeEnNrRsS780] ] [ -x[cCeEfFrRsSiuUwWxX] ] program [ arg... ]\n\
- Help: pty -H\n\
- X" ;
- X
- char *ptyhelp = "\
- pty runs a program under a pseudo-terminal session.\n\
- pty -ACHUVW: print authorship notice, copyright notice, this notice,\n\
- X short usage summary, version number, disclaimer of warranty\n\
- pty [-qQve3EdDjJsStTrR0] [-p[cCdDeEnNrRsS780]] [-x[cCeEfFrRsSiuUwWxX]] [-hhost]\n\
- X [-O remote] program [arg...]: run program under a pseudo-terminal\n\
- Options processed l to r. Capitals turn things off. Here + means default.\n\
- X-q: quiet (nothing on stderr) -e: leave fds 2 & 3 d=>T s=>E R=>T\n\
- X+Q: normal level of verbosity -3: leave fd 3 only d=dJT D=Djt 0=eSTp0\n\
- X-v: complain about everything +E: 2 & 3 both->pty s=sxu S=SxU p0=pcrEND\n\
- X-d: we are detached +j: job control +t: change orig tty to char mode\n\
- X+D: we have ctrl tty -J: ignore stops -T: leave orig tty alone\n\
- X-s: session (allow disconnect & reconnect) +r: read input\n\
- X+S: no session: disconnect will send HUP -R: output only (like rsh -n)\n\
- X-h host: use host in utmp/wtmp -O remote: use remote in sclog\n\
- X-p[cCdDeEnNrRsS78]: set pty modes; defaults taken from original tty if -D\n\
- X c: cbreak, character mode +n: change return to newline +e: echo\n\
- X +d: new line discipline r: raw, no keyboard signals +s: screen, crt\n\
- X-x[cCeEfFrRsSiuUwWxX]: security/experimental/extended, may be restricted\n\
- X c: chown pty e: pty's stderr wronly f: FIONREAD flow-control i: insecure\n\
- X +r: random pty w: /usr/adm/wtmp u: /etc/utmp x: TIOCEXCL s: extra-secure\n\
- If you have questions about or suggestions for pty, please feel free\n\
- to contact the author, Daniel J. Bernstein, at brnstnd@nyu.edu\n\
- on the Internet.\n\
- X" ;
- X/* ptyhelp *still* fits. Incredible. :-) */
- END_OF_FILE
- if test 3662 -ne `wc -c <'ptytexts.c'`; then
- echo shar: \"'ptytexts.c'\" unpacked with wrong size!
- fi
- # end of 'ptytexts.c'
- fi
- if test -f 'radixsort.3' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'radixsort.3'\"
- else
- echo shar: Extracting \"'radixsort.3'\" \(2915 characters\)
- sed "s/^X//" >'radixsort.3' <<'END_OF_FILE'
- X.TH radixsort 3
- X.SH NAME
- radixsort \- fast in-memory string sort
- X.SH SYNTAX
- X.B #include <radixsort.h>
- X
- int \fBradixsort7(\fIbase,n,endchar,table,index,ualloc,ufree\fB)\fR
- X
- int \fBradixsort5(\fIbase,n,endchar,table,index\fB)\fR
- X
- int \fBradixsort4(\fIbase,n,endchar,table\fB)\fR
- X
- int \fBradixsort3(\fIbase,n,endchar\fB)\fR
- X
- unsigned char \fI**base\fR;
- X.br
- int \fIn\fR;
- X.br
- unsigned int \fIendchar\fR;
- X.br
- unsigned char \fI*table\fR;
- X.br
- int \fIindex\fR;
- X.br
- char \fI*(*ualloc)()\fR;
- X.br
- void \fI(*ufree)()\fR;
- X.SH DESCRIPTION
- X.B radixsort7
- is a modified radix sort.
- It sorts an array,
- X.I base,
- of pointers to unsigned character strings.
- X.I base
- contains
- X.I n
- pointers.
- The strings are terminated by
- X.I (unsigned char) endchar
- and may contain any other characters.
- X
- X.B radixsort7
- allocates some temporary workspace
- using
- X.I ualloc
- and
- X.I ufree,
- which must provide the same interface as
- X.B malloc
- and
- X.B free.
- X.B radixsort5
- is the same as
- X.B radixsort7
- but with the default
- X.B malloc
- and
- X.B free.
- X
- X.B radixsort7
- sorts the array
- by lexical ASCII order of the strings,
- with
- X.I (unsigned char) endchar
- considered smaller than any other character.
- If
- X.I index
- is greater than zero,
- the first
- X.I index
- characters of each string are ignored,
- and sorting is based on the characters following.
- In other words, each pointer in
- X.I base
- is shifted by
- X.I index.
- This is useful for applications which want to store
- additional data in the first few bytes of each string.
- X.B radixsort4
- is the same as
- X.B radixsort5
- with
- X.I index
- set to 0.
- X
- X.I table
- provides more flexibility in the sort order.
- If it
- is non-zero,
- it must point to an array of
- UCHAR_MAX + 1 (i.e., the character set size, typically 256)
- unsigned characters
- containing the sort weight of each possible character in
- the strings.
- X.I endchar
- is ignored;
- instead,
- every character with sort weight 0
- in
- X.I table
- is considered a terminator.
- Any number of bytes can have the same sort weight;
- if, for instance, the table gives a-z the same weights as A-Z,
- X.B radixsort7
- will perform a case-insensitive sort.
- X.B radixsort3
- is the same as
- X.B radixsort4
- without a
- X.I table.
- X
- X.B radixsort7
- is stable: if two strings are equal, their pointers will
- remain in the same order in the sorted array.
- X.B radixsort7
- takes time
- at worst
- proportional to the total number of
- characters (including terminators) in the strings.
- This is within a constant factor of the
- information-theoretic optimum. In practice,
- X.B radixsort7
- is extremely fast.
- X
- X.B radixsort7
- returns 0 normally,
- X\-1 upon a memory allocation failure.
- X
- X.B radixsort(\fIbase,n,table,endchar\fB)
- is the same as
- X.B radixsort4(\fIbase,n,endchar,table\fB).
- It is deprecated.
- It is included here only for compatibility with BSD 4.4.
- X
- X.B radixsort7
- and its variants
- are
- X.B not
- safe to use inside signal handlers.
- X.SH VERSION
- radixsort/DJB 3.0, 7/23/91.
- X.SH AUTHORS
- Daniel J. Bernstein
- and
- Keith Bostic.
- X.SH "SEE ALSO"
- sort(1),
- qsort(3)
- END_OF_FILE
- if test 2915 -ne `wc -c <'radixsort.3'`; then
- echo shar: \"'radixsort.3'\" unpacked with wrong size!
- fi
- # end of 'radixsort.3'
- fi
- if test -f 'ralloc.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'ralloc.c'\"
- else
- echo shar: Extracting \"'ralloc.c'\" \(3779 characters\)
- sed "s/^X//" >'ralloc.c' <<'END_OF_FILE'
- X/* ralloc.c, ralloc.h: recovering alloc
- Daniel J. Bernstein, brnstnd@nyu.edu.
- Depends on sod.h.
- Requires malloc/free.
- X8/26/91: Changed exit() to _exit().
- X8/26/91: Made rallocneverfail() overwrite any previous handler.
- X7/24/91: Added rallocneverfail().
- X7/18/91: Baseline. ralloc 1.0, public domain.
- No known patent problems.
- X
- Lots of library routines allocate space for temporary objects: compiled
- regular expressions, for example. They don't destroy the objects between
- each call---wouldn't it be a waste to reallocate and recompile those
- regular expressions on every single pattern match? But when space gets
- tight, you don't want all those temporary objects cluttering the heap.
- You've got to deallocate them as soon as possible. Sure, library X might
- have some deallocation routines---but if X is hidden below library Y and
- separate library A runs out of space, do you expect A to know about X
- and call X's routines? Of course not. How can A and X coordinate?
- X
- The solution is ralloc. ralloc works just like malloc, except that when
- it runs out of memory, it tries to recover space from anyone who's
- willing to give a little slack. If f is a deallocation function, you can
- call rallocinstall(f), and ralloc(n) will call f() if there aren't n
- bytes free. f() should return a non-zero integer if it could free some
- memory, 0 if not. Several libraries can rallocinstall their deallocation
- routines, and ralloc will cycle between all of them. Make sure that f
- actually frees some memory if it returns non-zero---otherwise ralloc()
- will loop, trying f again and again and wondering why malloc() never has
- enough space. (In a future implementation I might add a loop counter and
- have ralloc give up after trying f enough times.)
- X
- According to John F. Haugh, ralloc is a Bad Thing, because it inherently
- requires static variables, hence can't be put into a ``pure'' shared
- library. Face it, John: ralloc() solves a real problem, and if you can't
- put it in a shared library, it's not because ralloc() is somehow evil.
- It's because your shared libraries aren't good enough.
- X
- X*/
- X
- X#include "ralloc.h"
- X#include "sod.h"
- extern char *malloc(); /*XXXX*/
- extern void free();
- X
- typedef int (*foo)();
- X
- SODdecl(funlist,foo);
- X
- static funlist funhead = 0;
- static funlist funlast = 0; /* last fun to successfully recover */
- X
- static int ralloccount = 0;
- X
- int rcount()
- X{
- X return ralloccount;
- X}
- X
- void rfree(s)
- char *s;
- X{
- X /* This is for completeness, and for another reason: so that you only */
- X /* have to modify this file if you want a debugging malloc-free. */
- X --ralloccount; /* for instance */
- X free(s);
- X}
- X
- static int crit = 0; /* just to be safe */
- X
- static int (*neverfail)() = 0;
- X
- static void die(n)
- unsigned n;
- X{
- X if (neverfail)
- X neverfail(n);
- X _exit(1); /*XXX*/
- X}
- X
- char *ralloc(n)
- unsigned n;
- X{
- X char *t;
- X funlist fun;
- X
- X if(t = malloc(n))
- X {
- X ++ralloccount;
- X return t;
- X }
- X if (crit)
- X if (neverfail)
- X die(n);
- X else
- X return 0;
- X if (!funhead)
- X if (neverfail)
- X die(n);
- X else
- X return 0;
- X crit = 1;
- X fun = (funlast ? SODnext(funlast) : funhead);
- X do
- X {
- X if(!fun)
- X fun = funhead;
- X if((*SODdata(fun))()) /* XXX: can we make use of args or return code? */
- X funlast = fun;
- X else
- X if(fun == funlast)
- X {
- X crit = 0;
- X if (neverfail)
- X die(n);
- X else
- X return 0; /* gaack! */
- X }
- X fun = SODnext(fun);
- X t = malloc(n);
- X }
- X while(!t);
- X ++ralloccount;
- X crit = 0;
- X return t;
- X}
- X
- void rallocneverfail(f)
- int (*f)();
- X{
- X neverfail = f; /* possibly overwriting previous handler */
- X}
- X
- X#define malloc ralloc
- X
- int rallocinstall(f)
- int (*f)();
- X{
- X funlist fun;
- X
- X fun = SODalloc(funlist,fun,ralloc);
- X if(!fun)
- X return -1;
- X SODdata(fun) = f;
- X SODpush(funhead,fun);
- X
- X funlast = funhead; /* need to set it to something */
- X
- X return 0;
- X}
- END_OF_FILE
- if test 3779 -ne `wc -c <'ralloc.c'`; then
- echo shar: \"'ralloc.c'\" unpacked with wrong size!
- fi
- # end of 'ralloc.c'
- fi
- if test -f 'sesslist.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'sesslist.c'\"
- else
- echo shar: Extracting \"'sesslist.c'\" \(3693 characters\)
- sed "s/^X//" >'sesslist.c' <<'END_OF_FILE'
- X/* XXX: this sort of depends on the dirent interface */
- X#undef POSIX /* JIC XXX */
- X#include <sys/types.h>
- X#include <sys/file.h>
- X#include <sys/dir.h>
- X#include <stdio.h>
- X#include "config/ptydir.h"
- X#include "config/ptylongname.h"
- X#include "fmt.h"
- X#include "scan.h"
- X#include "getopt.h"
- X#include "ptycomm.h"
- X
- main(argc,argv)
- int argc;
- char *argv[];
- X{
- X int uid;
- X DIR *dirp;
- X struct direct *dp;
- X int opt;
- X char sep;
- X int flagall;
- X
- X uid = getuid();
- X sep = '\n';
- X flagall = 0;
- X
- X while ((opt = getopt(argc,argv,"0a")) != opteof)
- X switch(opt)
- X {
- X case 'a':
- X flagall = 1;
- X break;
- X case '0':
- X sep = 0;
- X break;
- X case '?':
- X default:
- X exit(1);
- X }
- X argc -= optind; argv += optind;
- X
- X if (chdir(PTYDIR) == -1)
- X {
- X fprintf(stderr,"%s: fatal: cannot change to session directory %s\n",optprogname,PTYDIR);
- X exit(2);
- X }
- X
- X dirp = opendir(".");
- X while (dp = readdir(dirp))
- X {
- X unsigned int duid;
- X char dext[2];
- X char *t;
- X unsigned int len;
- X
- X t = dp->d_name;
- X len = scan_strncmp(t,"comm.",5);
- X if (len < 5)
- X ; /*XXX*/
- X t += len;
- X len = scan_uint(t,&duid);
- X if (len < 1)
- X ; /*XXX*/
- X t += len;
- X len = scan_strncmp(t,".",1);
- X if (len < 1)
- X ; /*XXX*/
- X t += len;
- X dext[0] = *t;
- X if (dext[0])
- X dext[1] = *++t;
- X else
- X dext[1] = 0;
- X
- X if ((duid == uid) || (flagall && !uid)) /*XXXX*/
- X {
- X int fdcomm;
- X int mslavepid;
- X int mpid;
- X char mrecoext[2];
- X char resp6[6];
- X int mflagsession;
- X char mlongname[PTYLONGNAMELEN];
- X static char outbuf[PTYLONGNAMELEN + 200];
- X char mext[2];
- X int mconn;
- X char *t;
- X
- X#define DO6 read(fdcomm,resp6,6);
- X#define BUMMER { close(fdcomm); continue; }
- X
- X fdcomm = comm_write(dext,uid);
- X if (fdcomm == -1)
- X continue;
- X if (write(fdcomm,"a",1) < 1)
- X BUMMER
- X DO6
- X if (write(fdcomm,"e",1) < 1)
- X BUMMER
- X if (read(fdcomm,mext,2) < 2)
- X BUMMER
- X if (write(fdcomm,"l",1) < 1)
- X BUMMER
- X DO6
- X if (!respeq(resp6,"longnm"))
- X BUMMER
- X if (read(fdcomm,mlongname,sizeof(mlongname)) < sizeof(mlongname))
- X BUMMER
- X if (write(fdcomm,"C",1) < 1)
- X BUMMER
- X DO6
- X mconn = respeq(resp6,"owuno?");
- X if (write(fdcomm,"p",1) < 1)
- X BUMMER
- X if (read(fdcomm,&mpid,sizeof(mpid)) < sizeof(mpid))
- X BUMMER
- X if (write(fdcomm,"P",1) < 1)
- X BUMMER
- X if (read(fdcomm,&mslavepid,sizeof(mslavepid)) < sizeof(mslavepid))
- X BUMMER
- X if (write(fdcomm,"D",1) < 1)
- X BUMMER
- X if (read(fdcomm,&mflagsession,sizeof(mflagsession)) < sizeof(mflagsession))
- X BUMMER
- X if (write(fdcomm,"S",1) < 1)
- X BUMMER
- X DO6
- X if (!respeq(resp6,"latest"))
- X BUMMER
- X if (read(fdcomm,mrecoext,2) < 2)
- X BUMMER
- X close(fdcomm);
- X
- X if ((mext[0] != dext[0]) || (mext[1] != dext[1]))
- X ; /* better to report what the master says */
- X
- X t = outbuf;
- X if (!mflagsession) t += fmt_strncpy(t,"non-",0);
- X t += fmt_strncpy(t,"session ",0);
- X *t++ = mext[0];
- X *t++ = mext[1];
- X t += fmt_strncpy(t," pid ",0);
- X t += fmt_uint(t,mpid);
- X t += fmt_strncpy(t," slave ",0);
- X t += fmt_uint(t,mslavepid);
- X if (mflagsession)
- X {
- X *t++ = ' ';
- X if (!mconn) t += fmt_strncpy(t,"dis",0);
- X t += fmt_strncpy(t,"connected",0);
- X }
- X if (mrecoext[0])
- X {
- X t += fmt_strncpy(t," (will drop into ",0);
- X *t++ = mrecoext[0];
- X *t++ = mrecoext[1];
- X *t++ = ')';
- X }
- X if (mlongname[0])
- X {
- X *t++ = ':';
- X *t++ = ' ';
- X t += fmt_strncpy(t,mlongname,0);
- X }
- X *t++ = sep;
- X
- X fwrite(outbuf,1,t - outbuf,stdout);
- X }
- X }
- X exit(0);
- X}
- END_OF_FILE
- if test 3693 -ne `wc -c <'sesslist.c'`; then
- echo shar: \"'sesslist.c'\" unpacked with wrong size!
- fi
- # end of 'sesslist.c'
- fi
- if test -f 'sessmenu.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'sessmenu.c'\"
- else
- echo shar: Extracting \"'sessmenu.c'\" \(3293 characters\)
- sed "s/^X//" >'sessmenu.c' <<'END_OF_FILE'
- X#include <stdio.h>
- extern char *malloc();
- X
- static char crterase[3] = { 8, ' ', 8 };
- X
- main(argc,argv,envp)
- int argc;
- char *argv[];
- char *envp[];
- X{
- X int flagecho;
- X int flagdisc;
- X int flagseveral;
- X FILE *fi;
- X int ch;
- X char okext1;
- X char okext2;
- X char ext1;
- X char ext2;
- X int i;
- X char cmd[200];
- X char **newargv;
- X
- X flagdisc = 0;
- X flagseveral = 0;
- X flagecho = 1;
- X
- X fi = popen("sesslist -0","r");
- X if (fi)
- X {
- X while ((ch = getc(fi)) != EOF)
- X {
- X if (ch == 's')
- X {
- X while (((ch = getc(fi)) != EOF) && (ch != ' '))
- X ;
- X if (ch == EOF) break;
- X if ((ch = getc(fi)) == EOF) break; ext1 = ch;
- X if ((ch = getc(fi)) == EOF) break; ext2 = ch;
- X for (i = 0;i < 5;++i)
- X {
- X while (((ch = getc(fi)) != EOF) && (ch != ' '))
- X ;
- X if (ch == EOF) break;
- X }
- X if (ch == EOF) break;
- X if ((ch = getc(fi)) != 'd') goto breakif;
- X
- X /* Now ext1 and ext2 give a disconnected session. */
- X if (flagdisc)
- X flagseveral = 1;
- X else
- X flagdisc = 1;
- X okext1 = ext1;
- X okext2 = ext2;
- X printf("You have a disconnected session on /dev/tty%c%c, with these processes:\r\n",ext1,ext2); fflush(stdout);
- X sprintf(cmd,"ps augxt%c%c | sed 's/$/\r/'",ext1,ext2);
- X system(cmd);
- X while (((ch = getc(fi)) != EOF) && (ch != 'd'))
- X ;
- X if ((ch = getc(fi)) == ':')
- X {
- X printf("Session %c%c is named:",ext1,ext2); fflush(stdout);
- X while (((ch = getc(fi)) != EOF) && ch)
- X putchar(ch);
- X printf(".\r\n"); fflush(stdout);
- X }
- X }
- X breakif: ;
- X if (ch == EOF) break;
- X if (ch)
- X while (((ch = getc(fi)) != EOF) && ch)
- X ;
- X if (ch == EOF) break;
- X }
- X pclose(fi); /* XXX: or maybe it's not worth waiting? */
- X }
- X
- X if (flagdisc)
- X {
- X char r1;
- X char r2;
- X int pos;
- X char ch;
- X
- X if (flagseveral)
- X sprintf(cmd,"\
- Would you like to reconnect to one of those sessions?\r\n\
- If so, type its two-character extension, like %c%c for the last one.\r\n\
- To instead start a new session as usual, just press return: ",okext1,okext2);
- X else
- X sprintf(cmd,"\
- Would you like to reconnect to that session?\r\n\
- If so, type its two-character extension, %c%c.\r\n\
- To instead start a new session as usual, just press return: ",okext1,okext2);
- X write(1,cmd,strlen(cmd));
- X
- X pos = 0;
- X while (read(0,&ch,1) == 1)
- X {
- X if ((ch == 8) || (ch == 127))
- X {
- X if (pos)
- X {
- X --pos;
- X if (flagecho)
- X write(1,crterase,3);
- X }
- X continue;
- X }
- X if ((ch == 10) || (ch == 13))
- X {
- X if (flagecho)
- X write(1,"\r\n",2);
- X if (pos < 2)
- X break;
- X sprintf(cmd,"exec pty -d reconnect %c%c",r1,r2);
- X execl("/bin/sh","sh","-c",cmd,(char *) 0);
- X /* XXX: warning? */
- X exit(1);
- X }
- X /* XXX: other special chars? */
- X switch(pos)
- X {
- X case 0:
- X r1 = ch;
- X ++pos;
- X if (flagecho)
- X write(1,&ch,1);
- X break;
- X case 1:
- X r2 = ch;
- X ++pos;
- X if (flagecho)
- X write(1,&ch,1);
- X break;
- X case 2:
- X ch = 7;
- X write(1,&ch,1);
- X break;
- X }
- X }
- X }
- X
- X newargv = (char **) malloc((argc + 4) * sizeof(char *));
- X if (!newargv)
- X exit(1); /*XXXX*/
- X
- X for (i = 0;i <= argc;++i)
- X newargv[i + 2] = argv[i + 1];
- X newargv[0] = "pty";
- X newargv[1] = "-ds";
- X execvp("pty",newargv,envp);
- X /* XXX: warning? */
- X exit(1);
- X}
- END_OF_FILE
- if test 3294 -ne `wc -c <'sessmenu.c'`; then
- echo shar: \"'sessmenu.c'\" unpacked with wrong size!
- fi
- # end of 'sessmenu.c'
- fi
- if test -f 'sessname.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'sessname.c'\"
- else
- echo shar: Extracting \"'sessname.c'\" \(2578 characters\)
- sed "s/^X//" >'sessname.c' <<'END_OF_FILE'
- X#include <stdio.h>
- X#include "ptycomm.h"
- X#include "config/ptydir.h"
- X#include "config/ptylongname.h"
- X#include "getopt.h"
- X#include "env.h"
- X
- main(argc,argv)
- int argc;
- char *argv[];
- X{
- X int opt;
- X int uid;
- X char *ext;
- X int fdcomm;
- X char resp6[6];
- X char longname[PTYLONGNAMELEN];
- X
- X uid = getuid();
- X ext = env_get("PTY");
- X while ((opt = getopt(argc,argv,"s:")) != opteof)
- X switch(opt)
- X {
- X case 's':
- X ext = optarg;
- X break;
- X case '?':
- X default:
- X exit(1);
- X }
- X argc -= optind;
- X argv += optind;
- X
- X if (*argv)
- X {
- X strncpy(longname,*argv,sizeof(longname));
- X longname[sizeof(longname) - 1] = 0;
- X }
- X
- X if (!ext)
- X {
- X fprintf(stderr,"%s: fatal: no -s specified, and PTY not set; are we under a session?\n",optprogname);
- X exit(2);
- X }
- X
- X if (chdir(PTYDIR) == -1)
- X {
- X fprintf(stderr,"%s: fatal: cannot change to session directory %s\n",optprogname,PTYDIR);
- X exit(2);
- X }
- X
- X fdcomm = comm_write(ext,uid);
- X if (fdcomm == -1)
- X {
- X fprintf(stderr,"%s: fatal: cannot find session %s; if it exists, do you own it?\n",optprogname,ext);
- X exit(2);
- X }
- X if (!*argv)
- X {
- X if (write(fdcomm,"l",1) < 1)
- X {
- X close(fdcomm);
- X fprintf(stderr,"%s: weird: session %s refuses to listen\n",optprogname,ext);
- X exit(2);
- X }
- X if (read(fdcomm,resp6,6) < 6)
- X {
- X close(fdcomm);
- X fprintf(stderr,"%s: weird: session %s refuses to respond\n",optprogname,ext);
- X exit(2);
- X }
- X if (!respeq(resp6,"longnm"))
- X {
- X close(fdcomm);
- X fprintf(stderr,"%s: weird: session %s is being quiet\n",optprogname,ext);
- X exit(2);
- X }
- X if (read(fdcomm,longname,sizeof(longname)) < sizeof(longname))
- X {
- X close(fdcomm);
- X fprintf(stderr,"%s: weird: session %s is being evasive\n",optprogname,ext);
- X exit(2);
- X }
- X close(fdcomm);
- X printf("session %c%c%s%s\n",ext[0],ext[1],longname[0] ? ": " : "",longname);
- X }
- X else
- X {
- X if (write(fdcomm,"L",1) < 1)
- X {
- X close(fdcomm);
- X fprintf(stderr,"%s: weird: session %s refuses to listen\n",optprogname,ext);
- X exit(2);
- X }
- X if (write(fdcomm,longname,sizeof(longname)) < sizeof(longname))
- X {
- X close(fdcomm);
- X fprintf(stderr,"%s: fatal: session %s is deaf\n",optprogname,ext);
- X exit(2);
- X }
- X if (read(fdcomm,resp6,6) < 6)
- X {
- X close(fdcomm);
- X fprintf(stderr,"%s: weird: session %s refuses to respond\n",optprogname,ext);
- X exit(2);
- X }
- X if (!respeq(resp6,"thanks"))
- X {
- X close(fdcomm);
- X fprintf(stderr,"%s: fatal: session %s refuses to change\n",optprogname,ext);
- X exit(2);
- X }
- X close(fdcomm);
- X }
- X
- X exit(0);
- X}
- END_OF_FILE
- if test 2578 -ne `wc -c <'sessname.c'`; then
- echo shar: \"'sessname.c'\" unpacked with wrong size!
- fi
- # end of 'sessname.c'
- fi
- if test -f 'sigdfl.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'sigdfl.c'\"
- else
- echo shar: Extracting \"'sigdfl.c'\" \(3017 characters\)
- sed "s/^X//" >'sigdfl.c' <<'END_OF_FILE'
- X/* sigdfl.c, sigdfl.h: default signal library
- Daniel J. Bernstein, brnstnd@nyu.edu.
- No dependencies.
- Requires BSD signal syscalls.
- X1/27/92: Added ABRT->IOT ifndef.
- X1/27/92: Switched from setting sv_flags to manually zeroing sigvecs.
- X7/18/91: Baseline. sigdfl 1.0, public domain.
- No known patent problems.
- X
- Documentation in sigdfl.3.
- X
- If you port this to System V, you don't have to worry about stop
- signals; you can just have sigdfl_tstp() and friends return -1 with
- XENOTTY. You are, however, faced with an incomplete, nearly prehistoric
- signal interface. Have fun.
- X*/
- X
- X#include <signal.h>
- X#include "sigdfl.h"
- X
- static int cont = 0;
- X
- static sigcont() /* XXX: should declare with right signal type */
- X{
- X cont = 1;
- X}
- X
- int sigdfl(sig)
- int sig;
- X{
- X int oldmask;
- X struct sigvec oldvec;
- X struct sigvec vec;
- X struct sigvec contvec;
- X char *x;
- X
- X if (sig == SIGCONT)
- X return 0; /* strategy below simply cannot work for CONT */
- X if ((sig == SIGURG) || (sig == SIGCHLD) || (sig == SIGIO)
- X#ifdef SIGWINCH
- X || (sig == SIGWINCH)
- X#endif
- X )
- X return 0; /* the above signals are ignored */
- X /* XXX: If we're still going now, and sig can be delivered without */
- X /* killing the process and without stopping the process so that it'll */
- X /* receive CONT later, then we will enter an infinite loop. [sigh] */
- X /* XXX: put maximum time wastage on this? */
- X oldmask = sigblock(0);
- X sigblock(~0);
- X /* now we won't receive any signals */
- X x = (char *) &vec; while (x < sizeof(vec) + (char *) &vec) *x++ = 0;
- X vec.sv_handler = SIG_DFL;
- X vec.sv_mask = ~0;
- X if (sigvec(sig,&vec,&oldvec) == -1)
- X if ((sig != SIGSTOP) && (sig != SIGKILL))
- X return -1;
- X x = (char *) &vec; while (x < sizeof(vec) + (char *) &vec) *x++ = 0;
- X vec.sv_handler = sigcont;
- X vec.sv_mask = ~0;
- X if (sigvec(SIGCONT,&vec,&contvec) == -1)
- X return -1;
- X cont = 0;
- X if (kill(getpid(),sig) == -1)
- X return -1;
- X /* now a sig should be queued, and we have control over sig and CONT */
- X /* exception: SIGSTOP and SIGKILL can't be blocked, so those signals
- X might already have been delivered. in the SIGSTOP case, if we've
- X reached this point, sigcont() might already have been run. that's
- X why cont must be set to 0 before the kill(). */
- X /* after this next bit we may receive sig and/or CONT */
- X sigsetmask(~(sigmask(sig) | sigmask(SIGCONT)));
- X /* in the near future, sig will in fact be received */
- X while (!cont) /* dead loop until we receive CONT */
- X ; /* XXX: there should be a syscall so we don't have to loop here */
- X sigblock(~0);
- X /* now we won't receive any signals */
- X (void) sigvec(sig,&oldvec,&vec); /* we don't care if it fails */
- X (void) sigvec(SIGCONT,&contvec,&vec);
- X /* now signal handlers are back to normal */
- X (void) sigsetmask(oldmask);
- X return 0;
- X}
- X
- int sigdfl_tstp()
- X{
- X return sigdfl(SIGTSTP);
- X}
- X
- int sigdfl_stop()
- X{
- X return sigdfl(SIGSTOP);
- X}
- X
- int sigdfl_ttin()
- X{
- X return sigdfl(SIGTTIN);
- X}
- X
- int sigdfl_ttou()
- X{
- X return sigdfl(SIGTTOU);
- X}
- X
- int sigdfl_abrt()
- X{
- X#ifndef SIGABRT
- X#define SIGABRT SIGIOT
- X#endif
- X return sigdfl(SIGABRT);
- X}
- END_OF_FILE
- if test 3017 -ne `wc -c <'sigdfl.c'`; then
- echo shar: \"'sigdfl.c'\" unpacked with wrong size!
- fi
- # end of 'sigdfl.c'
- fi
- if test -f 'who.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'who.c'\"
- else
- echo shar: Extracting \"'who.c'\" \(2317 characters\)
- sed "s/^X//" >'who.c' <<'END_OF_FILE'
- X/* who.c: clone of who program
- Daniel J. Bernstein, brnstnd@nyu.edu.
- Depends on getopt.h, fmt.h.
- Requires BSD-style utmp and gethostname.
- X7/22/91: Baseline. who 2.0, public domain.
- No known patent problems.
- X
- Documentation in who.1.
- X
- This is based on the who.c that came with pty 3.0 but is much cleaner.
- X*/
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <utmp.h>
- X#include <time.h>
- extern char *asctime();
- extern char *ttyname();
- X#include "config/utmpfile.h"
- X#include "getopt.h"
- X#include "fmt.h"
- X
- main(argc,argv)
- int argc;
- char *argv[];
- X{
- X int opt;
- X int flagloggedin;
- X int flagwhoami;
- X char *ttyn;
- X static struct utmp ut;
- X static char hostname[120];
- X char *fn;
- X FILE *fi;
- X static char output[500];
- X char *t;
- X unsigned int len;
- X
- X flagloggedin = 2;
- X flagwhoami = 0;
- X while ((opt = getopt(argc,argv,"lL")) != opteof)
- X switch(opt)
- X {
- X case 'L':
- X flagloggedin = 1;
- X break;
- X case 'l':
- X flagloggedin = 0;
- X break;
- X case '?':
- X default:
- X exit(1);
- X }
- X argc -= optind;
- X argv += optind;
- X
- X if (argc > 1)
- X {
- X flagwhoami = 1;
- X if (!isatty(0))
- X {
- X fprintf(stderr,"who: fatal: stdin not a tty\n");
- X exit(1);
- X }
- X ttyn = ttyname(0) + 5; /* XXX: /dev/ */
- X gethostname(hostname,sizeof(hostname));
- X }
- X
- X if (flagloggedin == 2)
- X flagloggedin = !argc;
- X fn = ((argc == 1) ? argv[0] : UTMP_FILE);
- X
- X if (!(fi = fopen(fn,"r")))
- X {
- X t = output;
- X t += fmt_strncpy(t,"who: cannot open ",0);
- X t += fmt_strncpy(t,fn,(output + sizeof(output)) - t - 3);
- X *t = 0;
- X perror(output);
- X exit(1);
- X }
- X
- X while (fread((char *) &ut,sizeof(ut),1,fi))
- X {
- X if (ut.ut_name[0] || !flagloggedin)
- X if (!flagwhoami || !strncmp(ut.ut_line,ttyn,8))
- X {
- X t = output;
- X if (flagwhoami)
- X {
- X t += fmt_strncpy(t,hostname,0);
- X *t++ = '!';
- X }
- X len = fmt_strncpy(t," ",0);
- X t[fmt_strncpy(t,ut.ut_name,len)] = ' '; t += len; *t++ = ' ';
- X len = fmt_strncpy(t," ",0);
- X t[fmt_strncpy(t,ut.ut_line,len)] = ' '; t += len;
- X len = fmt_strncpy(t," ",0);
- X t[fmt_strncpy(t,asctime(localtime(&ut.ut_time)) + 4,len)] = ' ';
- X t += len;
- X if (ut.ut_host[0])
- X {
- X *t++ = '\t';
- X *t++ = '(';
- X t += fmt_strncpy(t,ut.ut_host,16);
- X *t++ = ')';
- X }
- X *t = 0;
- X puts(output);
- X }
- X }
- X exit(0);
- X}
- END_OF_FILE
- if test 2317 -ne `wc -c <'who.c'`; then
- echo shar: \"'who.c'\" unpacked with wrong size!
- fi
- # end of 'who.c'
- fi
- if test -f 'write.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'write.c'\"
- else
- echo shar: Extracting \"'write.c'\" \(2757 characters\)
- sed "s/^X//" >'write.c' <<'END_OF_FILE'
- X/* Public domain. */
- X
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <sys/file.h>
- X#ifdef BSD
- X#include <limits.h>
- X#endif
- X#include <stdio.h>
- X#include <strings.h>
- X#include <utmp.h>
- X#include <pwd.h>
- X#include <time.h>
- X#include "config/utmpfile.h"
- X#include "fmt.h"
- extern unsigned short getuid();
- extern char *ttyname();
- extern long time();
- X
- main(argc,argv)
- int argc;
- char *argv[];
- X{
- X register FILE *fi;
- X struct utmp ut;
- X char line[9];
- X int lines = 0;
- X char fntty[30];
- X int fd;
- X struct stat st;
- X char buf[500];
- X char outbuf[3000];
- X int offset;
- X char *username;
- X struct passwd *pw;
- X char hostname[64];
- X char *ttyn;
- X long t;
- X struct tm *tm;
- X char *s;
- X
- X if (argc < 2)
- X {
- X fputs("Usage: write user [ttyname]\n",stderr);
- X exit(1);
- X }
- X
- X if (!(pw = getpwuid((int) getuid())))
- X {
- X fputs("write: who are you?\n",stderr);
- X exit(1);
- X }
- X username = pw->pw_name;
- X
- X gethostname(hostname,sizeof(hostname));
- X hostname[sizeof(hostname) - 1] = 0;
- X
- X if (!(ttyn = ttyname(2)))
- X {
- X fputs("write: Can't find your tty\n",stderr);
- X exit(1);
- X }
- X if ((fstat(2,&st) == -1) || !(st.st_mode & 0020))
- X fputs("write: warning: your messages are off, recipient will not be able to respond\n",stderr);
- X
- X t = time((long *) 0);
- X tm = localtime(&t);
- X
- X if (fi = fopen(UTMP_FILE,"r"))
- X while (fread((char *) &ut,sizeof(ut),1,fi))
- X if (!strncmp(ut.ut_name,argv[1],8))
- X if ((argc == 2) || (!strncmp(ut.ut_line,argv[2],8)))
- X if (!lines)
- X {
- X fmt_strncpy(line,ut.ut_line,8);
- X line[8] = '\0';
- X lines = 1;
- X }
- X else
- X lines++;
- X if (!lines)
- X {
- X if (argc == 2)
- X (void) fprintf(stderr,"write: %s not logged in\n",argv[1]);
- X else
- X (void) fprintf(stderr,"write: %s not logged in on tty %s\n",
- X argv[1],argv[2]);
- X (void) exit(1);
- X }
- X if (lines > 1)
- X (void) fprintf(stderr,
- X "write: %s logged in more than once ... writing to %s\n",
- X argv[1],line);
- X
- X (void) sprintf(fntty,"/dev/%s",line);
- X if ((fd = open(fntty,O_WRONLY)) == -1)
- X {
- X fputs("write: Permission denied\n",stderr);
- X exit(1);
- X }
- X
- X (void) sprintf(buf,"\nMessage from %s@%s on %s at %d:%02d ...%c\n",
- X username,hostname,ttyn + 5,tm->tm_hour,tm->tm_min,7);
- X (void) write(fd,buf,strlen(buf));
- X
- X (void) sprintf(buf,"%s: ",username);
- X offset = strlen(buf);
- X
- X while (fgets(buf + offset,sizeof(buf) - offset,stdin))
- X {
- X if ((fstat(fd,&st) == -1) || !(st.st_mode & 0020))
- X {
- X fprintf(stderr,"write: Permission denied\n");
- X exit(1);
- X }
- X s = outbuf + fmt_nvis(outbuf,buf,strlen(buf));
- X write(fd,outbuf,s - outbuf); /*XXX*/
- X sleep(1);
- X }
- X
- X t = time((long *) 0);
- X tm = localtime(&t);
- X (void) sprintf(buf,"End of message from %s@%s on %s at %d:%02d\n",
- X username,hostname,ttyn + 5,tm->tm_hour,tm->tm_min);
- X (void) write(fd,buf,strlen(buf));
- X
- X exit(0);
- X}
- END_OF_FILE
- if test 2757 -ne `wc -c <'write.c'`; then
- echo shar: \"'write.c'\" unpacked with wrong size!
- fi
- # end of 'write.c'
- fi
- echo shar: End of archive 3 \(of 9\).
- cp /dev/null ark3isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 9 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-